<?php

namespace App\Biz;

use App\Exceptions\TokenExpiredException;
use App\Models\BaseMode;
use App\Models\IntervieweeInformation;
use Closure;
use Exception;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Validator;
use Psr\SimpleCache\InvalidArgumentException;

class IntervieweeBiz extends BaseBiz
{
    protected HttpBiz $httpBiz;
    protected ConfigBiz $configBiz;
    protected int $maxRetry = 3;

    /**
     * @param IntervieweeInformation $intervieweeInformation
     * @param ConfigBiz $configBiz
     * @param HttpBiz $httpBiz
     * @throws Exception
     */
    public function __construct(IntervieweeInformation $intervieweeInformation, ConfigBiz $configBiz, HttpBiz $httpBiz)
    {
        if (!$intervieweeInformation->getAttributes()) {
            throw new Exception('受访者信息为空');
        }

        $this->model     = $intervieweeInformation;
        $this->configBiz = $configBiz;
        $this->httpBiz   = $httpBiz;
    }


    /**
     * 受访者登录
     * @return Collection
     * @throws TokenExpiredException|Exception|InvalidArgumentException
     */
    public function intervieweeLoginAndCache(): Collection
    {
        $response = $this->httpBiz->intervieweeLogin(
            $this->configBiz->getConfig()->authorId,
            $this->model->openId,
            $this->model->phone
        );

        Validator::validate($response->toArray(), [
            'token'     => 'required',
            'telephone' => 'required',
            'personId'  => 'required',
            'name'      => 'required',
        ]);

        Cache::set($this->model->phone, $response, 60 * 10);

        return $response;
    }


    /**
     * 获取登录返回信息不存在则登录
     * @return Collection
     */
    public function getResponseLoginData(): Collection
    {
        return Cache::remember($this->model->phone, 60 * 10, function () {
            return $this->intervieweeLoginAndCache();
        });
    }

    /**
     * token
     * @return string
     */
    public function token(): string
    {
        return $this->getResponseLoginData()->get('token');
    }

    /**
     * 访客预约列表
     * @return Collection
     * @throws Exception|InvalidArgumentException
     */
    public function visitorReservesList(): Collection
    {
        return $this->request(function () {
            return $this->httpBiz->visitorReservesList($this->token());
        });
    }

    /**
     * 访客预约审核
     * @param string $uniqueId
     * @return false|mixed
     * @throws InvalidArgumentException
     */
    public function visitorReservesApproval(string $uniqueId): mixed
    {
        try {
            return $this->request(function () use ($uniqueId) {
                return $this->httpBiz->visitorReservesApproval(
                    $this->token(),
                    $this->configBiz->getConfig()->appId,
                    $uniqueId,
                    BaseMode::STATUS_OPEN
                );
            });

        } catch (Exception $e) {
            Log::error("{$this->model->name} 受访者审核失败 {$e->getMessage()} ");
        }
        return false;
    }

    /**
     * 发送请求
     * @param Closure $closure
     * @return mixed
     * @throws Exception|InvalidArgumentException
     *
     */
    public function request(Closure $closure): mixed
    {
        return retry($this->maxRetry, $closure, 3, function ($e) {
            return $e instanceof TokenExpiredException ? $this->intervieweeLoginAndCache() : true;
        });
    }
}
